#pragma once

#define EREM(post,bf)\
bf=0;\
for(int i=0;i<post;i++){\
	if(vstr[i].str==""){\
		bf++;\
	}\
}\
for(int i=0;i<vstr.size();){\
	if(vstr[i].str==""){\
		vstr.erase(vstr.begin()+i,vstr.begin()+i+1);\
	}else{\
		i++;\
	}\
}\
post-=bf

struct error{
	string mess;
	error(const string&str):mess(str){}
};

value atov(const string &str){
	if(str[0]=='\"'){
		value v;
		v.ty=Z_STR;
		string a=str;
		a=a.c_str()+1;
		a.erase(a.size()-1,a.size()-1);
		v.data.strp=new string(a);
		pool.insert(v.data.strp);
		return v;
	}
	if((str[0]>='0'&&str[0]<='9')||str[0]=='+'||str[0]=='-'){
		value v;
		if(str.find('.')!=string::npos){
			v.ty=Z_REAL;
			v.data.ld=stold(str.c_str());
		}else{
			v.ty=Z_INT;
			v.data.ll=stoll(str.c_str());
		}
		return v;
	}
	return value();
}

vector<token> explain(vector<token> vstr,int pc){
	/* zhushi chuli */
	for(int a=0;a<vstr.size();a++){
		if(vstr[a].str=="//"){
			vstr.erase(vstr.begin()+a, vstr.end());
			break;
		}
	}
	int bf;
	/* GJZ 关键字 */
	for(int a=0;a<vstr.size();a++){
		if(vstr[a].str==""){
			continue;
		}
		if(vstr[a].wv==Z_GJZ){
			if(vstr[a].str=="print"){
				vector<vector<token>> vtt;int pk=0;vector<token> vt;
				if(a+1>=vstr.size()){
					throw error("SyntaxError : Expect a \'(\' after print but not found");
				}
				if(vstr[a+1].str=="("){
					vstr[a].str="";
					vstr[a+1].str="";
					a+=2;
					for(;pk||vstr[a].str!=")";a++){
						if(a>=vstr.size()){
							throw error("SyntaxError : Expect a ')' in the end of the line");
						}
						//cout<<vstr[a].str<<"|";
						if(vstr[a].str=="("){
							pk++;
						}else if(vstr[a].str==")"){
							pk--;
						}
						if(pk){
							vt.push_back(vstr[a]);
						}else{
							if(vstr[a].str==","){
								vtt.push_back(vt);
								vt.clear();
							}else{
								vt.push_back(vstr[a]);
							}
						}
						vstr[a].str="";
						//cout<<"|"<<vstr[a].str<<"|";
					}
					vstr[a].str="";
					vtt.push_back(vt);
				}else{
					throw(error("SyntaxError : Expect a \'(\' after print but not found"));
				}
				for(vector<token> &onarg:vtt){
					for(token &onet:explain(onarg,pc)){
						//cout<<"{"<<onet.str<<"}";
						if(onet.str=="")continue;
						value va=atov(onet.str);
						switch(va.ty){
							case Z_REAL:
								cout<<va.data.ld;
								break;
							case Z_INT:
								cout<<va.data.ll;
								break;
							case Z_STR:
								cout<<*va.data.strp;
								break;
							default:
								//cout<<int(va.ty);
								throw error("RuntimeError : Can\'t output the value that\'s type is a unknown type");
								break;
						}
					}
				}
			}else if(vstr[a].str=="in"){
				vector<vector<token>> vtt;int pk=0;vector<token> vt;int olda=a;
				if(a+1>=vstr.size()){
					throw error("SyntaxError : Expect a \'(\' after print but not found");
				}
				if(vstr[a+1].str=="("){
					vstr[a].str="";
					vstr[a+1].str="";
					a+=2;
					for(;pk||vstr[a].str!=")";a++){
						if(a>=vstr.size()){
							throw error("SyntaxError : Expect a ')' in the end of the line");
						}
						//cout<<vstr[a].str<<"|";
						if(vstr[a].str=="("){
							pk++;
						}else if(vstr[a].str==")"){
							pk--;
						}
						if(pk){
							vt.push_back(vstr[a]);
						}else{
							if(vstr[a].str==","){
								vtt.push_back(vt);
								vt.clear();
							}else{
								vt.push_back(vstr[a]);
							}
						}
						vstr[a].str="";
						//cout<<vstr[a].str;
					}
					vstr[a].str="";
					vtt.push_back(vt);
				}else{
					throw(error("SyntaxError : Expect a \'(\' after print but not found"));
				}
				for(vector<token> &onarg:vtt){
					for(token &onet:explain(onarg,pc)){
						//cout<<"{"<<onet.str<<"}";
						value va=atov(onet.str);
						switch(va.ty){
							case Z_REAL:
							case Z_STR:
							case Z_INT:{
								if(olda==-1){
									throw error("Syntax error: Only one arg is expected at most in the in parameter section.");
								}
								string str;
								cin>>str;
								if(va.ty==Z_STR){
									str="\""+str+"\"";
								}
								vstr[olda].str=str;
								vstr[olda].wv=Z_ATOMIC;
								olda=-1;
								break;
							}
							default:
								//cout<<va.ty; 
								throw error("RuntimeError : Can\'t input the value that\'s type is a unknown type");
								break;
						}
					}
				}
			}else if(vstr[a].str=="exit"){
				vector<vector<token>> vtt;int pk=0;vector<token> vt;
				if(a+1>=vstr.size()){
					throw error("SyntaxError : Expect a \'(\' after print but not found");
				}
				if(vstr[a+1].str=="("){
					vstr[a].str="";
					vstr[a+1].str="";
					a+=2;
					for(;pk||vstr[a].str!=")";a++){
						if(a>=vstr.size()){
							throw error("SyntaxError : Expect a ')' in the end of the line");
						}
						//cout<<vstr[a].str<<"|";
						if(vstr[a].str=="("){
							pk++;
						}else if(vstr[a].str==")"){
							pk--;
						}
						if(pk){
							vt.push_back(vstr[a]);
						}else{
							if(vstr[a].str==","){
								vtt.push_back(vt);
								vt.clear();
							}else{
								vt.push_back(vstr[a]);
							}
						}
						vstr[a].str="";
						//cout<<"|"<<vstr[a].str<<"|";
					}
					vstr[a].str="";
					vtt.push_back(vt);
				}else{
					throw(error("SyntaxError : Expect a \'(\' after print but not found"));
				}
				for(vector<token> &onarg:vtt){
					for(token &onet:explain(onarg,pc)){
						//cout<<"{"<<onet.str<<"}";
						if(onet.str=="")continue;
						value va=atov(onet.str);
						switch(va.ty){
							case Z_INT:
								exit(va.data.ll);
								break;
							default:
								//cout<<int(va.ty);
								throw error("RuntimeError : Can\'t exit the value that\'s type is a unknown type");
								break;
						}
					}
				}
			}
			else{
				throw(error(string("SyntaxError : No such command \'")+vstr[a].str+"\'"));
			}
			EREM(a,bf);
		}
	}

	/*mul math*/
	for(int a=0;a<vstr.size();a++){
		if(vstr[a].str.empty())continue;
		if(vstr[a].wv==Z_MUL_MATH){
			if(a+1>vstr.size()||vstr[a+1].wv!=Z_ATOMIC){
				throw error("SyntaxError : Expect a atom after * or /");
			}
			if(a>0&&vstr[a-1].wv==Z_ATOMIC){
				value val=atov(vstr[a-1].str),val2;
				switch(val.ty){
					case Z_INT:
						val2=atov(vstr[a+1].str);
						if(val2.ty==Z_INT){
							if(vstr[a].str=="*"){
								val.data.ll*=val2.data.ll;
							}else if(vstr[a].str=="/"){
								val.data.ll/=val2.data.ll;
							}else if(vstr[a].str=="%"){
								val.data.ll%=val2.data.ll;
							}else{
								throw error("SyntaxError : Expect * , / or % but is not");
							}
							vstr[a].str=to_string(val.data.ll);
						}else{
							throw error("123456789");
						}
						break;
					case Z_REAL:
						val2=atov(vstr[a+1].str);
						if(val2.ty==Z_REAL){
							if(vstr[a].str=="*"){
								val.data.ld*=val2.data.ld;
							}else if(vstr[a].str=="/"){
								val.data.ld/=val2.data.ld;
							}else if(vstr[a].str=="%"){
								throw error("SyntaxError : Can\'t use % at real");
							}else{
								throw error("SyntaxError : Expect * or / but is not");
							}
							vstr[a].str=to_string(val.data.ld);
						}else{
							throw error("123456789");
						}
						break;
					case Z_STR:
						
						break;
					default:
						throw error("RuntimeError : Can\'t use * , / or % in the type");
						break;
				}
				vstr[a].wv=Z_ATOMIC;
				vstr[a-1].str=(vstr[a+1].str="");
			}else{
				throw error("SyntaxError : Expect a atom before * , / or % but not found");
			}
			EREM(a,bf);
		}
	}

	/*add math*/
	for(int a=0;a<vstr.size();a++){
		if(vstr[a].str.empty())continue;
		if(vstr[a].wv==Z_ADD_MATH){
			if(a+1>vstr.size()||vstr[a+1].wv!=Z_ATOMIC){
				throw error("SyntaxError : Expect a atom after + or -");
			}
			if(a>0&&vstr[a-1].wv==Z_ATOMIC){
				value val=atov(vstr[a-1].str),val2;
				switch(val.ty){
					case Z_INT:
						val2=atov(vstr[a+1].str);
						if(val2.ty==Z_INT){
							if(vstr[a].str=="+"){
								val.data.ll+=val2.data.ll;
							}else if(vstr[a].str=="-"){
								val.data.ll-=val2.data.ll;
							}else{
								throw error("SyntaxError : Expect + or - but is not");
							}
							vstr[a].str=to_string(val.data.ll);
						}else{
							throw error("123456789");
						}
						break;
					case Z_REAL:
						val2=atov(vstr[a+1].str);
						if(val2.ty==Z_REAL){
							if(vstr[a].str=="+"){
								val.data.ld+=val2.data.ld;
							}else if(vstr[a].str=="-"){
								val.data.ld-=val2.data.ld;
							}else{
								throw error("SyntaxError : Expect + or - but is not");
							}
							vstr[a].str=to_string(val.data.ld);
						}else{
							throw error("123456789");
						}
						break;
					case Z_STR:
						
						break;
					default:
						throw error("RuntimeError : Can\'t use + or - in the type");
						break;
				}
				vstr[a].wv=Z_ATOMIC;
				vstr[a-1].str=(vstr[a+1].str="");
			}else{
				
			}
			EREM(a,bf);
		}
	}
	return vstr;
}